﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using intelliEssay.Interop.FontServices;

namespace intelliEssay.Interop
{
    /// <summary>
    /// This class contains extension methods to facillitate coding
    /// </summary>
    public static class Extentions
    {
        static string s = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        static string p = "。，”“：；、！？";
        /// <summary>
        /// This extension helps test whether the given char is in alphabet or is an arabic number
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool InAlphabetOrNumber(this char c)
        {
            return s.Contains(c);
        }
        /// <summary>
        /// This extension helps test if the given char is a punctuation
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsPunctuation(this char c)
        {
            return p.Contains(c);
        }
        /// <summary>
        /// This extension determines if the given char should cause a space to be added between two runs
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool IsSyntaxRequringAdditionalSpacingBetweenRun(this char c)
        {
            return c.IsPunctuation() || c.InAlphabetOrNumber();
        }
        /// <summary>
        /// This extension determines the last character's index plus 1 that is NOT a space
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static int GetLastCharacterNotSpaceCount(this string s)
        {
            for (int i = s.Length - 1; i >= 0; i--)
            {
                if (s[i] != ' ')
                {
                    return s.Length - i;
                }
            }
            return s.Length;
        }
        /// <summary>
        /// This extension determines the First non-space char's index PLUS 1 in the given string
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static int GetFirstCharacterNotSpaceCount(this string s)
        {
            for (int i = 0; i < s.Length; i++)
            {
                if (s[i] != ' ')
                {
                    return i + 1;
                }
            }
            return s.Length;
        }
        /// <summary>
        /// This extension determines the length of the run in milimeter, counting starting Whitespaces
        /// this extension requires the intelliEssay.Interop assembly to be referenced
        /// </summary>
        /// <param name="run"></param>
        /// <param name="wd"></param>
        /// <param name="addAdditionalSpace"></param>
        /// <returns></returns>
        public static double GetRunCharacterLengthCountingWhiteSpace(this Run run, WordprocessingDocument wd, bool addAdditionalSpace = false)
        {
            double ftsz = 10.5;
            double spacing = 0.1;
            double charScaleRatio = 1.00;
            RunInfo ri = (new RunInfoHelper(wd)).GetRunInfo(run);
            ftsz = double.Parse(ri.FontSize) / 2 * UnitConversion.PointInMilimeter;
            spacing = ri.Spacing / 20 * UnitConversion.PointInMilimeter;
            charScaleRatio = ri.CharacterScale / 100 + 1;
            int LetterOrDigitCount = run.InnerText.Where<char>(o =>
            {
                return o.InAlphabetOrNumber() || o.IsPunctuation() || o == ' ';
            }).Count();
            double result;
            if (run.InnerText.Length > 1)
            {
                result = (ftsz * charScaleRatio + spacing) * (run.InnerText.Length - LetterOrDigitCount) - spacing + (LetterOrDigitCount) * (ftsz * charScaleRatio + spacing) / 2;
            }
            else
            {
                result = (ftsz * charScaleRatio + spacing) * (run.InnerText.Length - LetterOrDigitCount) + (ftsz * charScaleRatio + spacing) / 2 * LetterOrDigitCount;
            }
            if (addAdditionalSpace)
            {
                result += (ftsz * charScaleRatio + spacing) / 2;
            }
            return result += (ftsz * charScaleRatio + spacing) * (LetterOrDigitCount / 2);
        }
        /// <summary>
        /// This extension helps decide the length of the run, ignoring the starting white space characters.
        /// Thie extendion requires the intelliEssay.Interop to be referenced.
        /// </summary>
        /// <param name="run"></param>
        /// <param name="wd"></param>
        /// <param name="addAdditionalSpace"></param>
        /// <returns></returns>
        public static double GetRunCharacterLengthIgnoringStartingWhiteSpace(this Run run, WordprocessingDocument wd, bool addAdditionalSpace = false)
        {
            double ftsz = 10.5;
            double spacing = 0.1;
            double charScaleRatio = 1.00;
            RunInfo ri = (new RunInfoHelper(wd)).GetRunInfo(run);
            ftsz = double.Parse(ri.FontSize) / 2 * UnitConversion.PointInMilimeter;
            spacing = ri.Spacing / (20.0) * UnitConversion.PointInMilimeter;
            charScaleRatio = ri.CharacterScale / 100 + 1;
            int LetterOrDigitCount = run.InnerText.Where<char>(o =>
              {
                  return o.InAlphabetOrNumber() || o.IsPunctuation() || o == ' ';
              }).Count();
            // int idx = run.InnerText.GetFirstCharacterNotSpaceCount();
            int startingSpaceCount = run.InnerText.Length - run.InnerText.TrimStart().Length;
            int effectiveSpaceCount = LetterOrDigitCount - startingSpaceCount;
            double result;
            if (run.InnerText.Length - startingSpaceCount > 1)
            {
                result = (run.InnerText.Length - LetterOrDigitCount) * (spacing + ftsz * charScaleRatio) - spacing + (effectiveSpaceCount) * (spacing + ftsz * charScaleRatio) / 2;
            }
            else
            {
                result = (run.InnerText.Length - LetterOrDigitCount) * (spacing + ftsz * charScaleRatio) + effectiveSpaceCount * (spacing + ftsz * charScaleRatio) / 2;
            }
            if (addAdditionalSpace)
            {
                result += (spacing + ftsz * charScaleRatio) / 2;
            }
            return result;
        }
        internal static HostApplications ToHostApplicationEnumeration(this int i)
        {
            if (i == 1)
            {
                return HostApplications.MsOffice2010;
            }
            return HostApplications.MsOffice2010;
        }
    }
}
